import { ReplaySubject, share, Observable, type Subscription } from 'rxjs';
import { createDelayPublish } from '@/utils/pipeFns/time';

class NotifyOption {
    msg = '';
    type?: '' | 'primary' | 'success' | 'warning' | 'danger' | 'info';
    position?: '' | 'top' | 'center' | 'bottom';
    textColor?: string;
    bgColor?: string;
    duration?: number;
}

class NotifyManager {
    private notifySubject: ReplaySubject<NotifyOption> | undefined;
    private source$: Observable<NotifyOption> | undefined;
    private subscription: Subscription | undefined;

    // time = 0;

    private static instance: NotifyManager | undefined;

    private static getInstance(): NotifyManager {
        if (NotifyManager.instance === undefined) {
            NotifyManager.instance = new NotifyManager();
        }
        return NotifyManager.instance;
    }

    private constructor() {
        this.notifySubject = new ReplaySubject<NotifyOption>(5);
        const delayPublish = createDelayPublish(2000);
        this.source$ = this.notifySubject.pipe(
            share({
                resetOnRefCountZero: false
            }),
            delayPublish()
        );
    }

    static success(option: NotifyOption) {
        const instance = NotifyManager.getInstance();
        instance.notifySubject?.next({
            type: 'success',
            position: 'top',
            ...option
        });
    }

    static danger(option: NotifyOption) {
        const instance = NotifyManager.getInstance();
        instance.notifySubject?.next({
            type: 'danger',
            position: 'top',
            ...option
        });
    }

    static info(option: NotifyOption) {
        const instance = NotifyManager.getInstance();
        instance.notifySubject?.next({
            type: 'info',
            position: 'center',
            ...option
        });
    }

    static onNotify(fn: (option: NotifyOption) => void) {
        const instance = NotifyManager.getInstance();
        const subscription = instance.source$?.subscribe({
            next: (option) => {
                fn(option);
            }
        });
        if (instance.subscription === undefined) {
            instance.subscription = subscription;
        } else {
            instance.subscription.add(subscription);
        }
    }

    static dispose() {
        const instance = NotifyManager.getInstance();
        instance.notifySubject?.complete();
        instance.subscription?.unsubscribe();
        instance.notifySubject?.unsubscribe();
        instance.notifySubject = undefined;
        instance.source$ = undefined;
        NotifyManager.instance = undefined;
    }
}

export const useNotifySubject = () => {
    const dispose = () => {
        NotifyManager.dispose();
    };

    const success = (option: NotifyOption) => {
        NotifyManager.success(option);
    };

    const danger = (option: NotifyOption) => {
        NotifyManager.danger(option);
    };

    const info = (option: NotifyOption) => {
        NotifyManager.info(option);
    };

    const onNotify = (fn: (option: NotifyOption) => void) => {
        NotifyManager.onNotify(fn);
    };

    return {
        onNotify,
        success,
        danger,
        info,
        dispose
    };
};
